package es.cazadoresmadridejos.beans.controller.budget;

import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.servlet.ModelAndView;

import es.cazadoresmadridejos.beans.manager.budget.BudgetManager;
import es.cazadoresmadridejos.beans.manager.reason.ReasonManager;
import es.cazadoresmadridejos.beans.validator.budget.BudgetValidator;
import es.cazadoresmadridejos.model.Budget;
import es.cazadoresmadridejos.model.BudgetLine;
import es.cazadoresmadridejos.model.BudgetLine.LineType;
import es.cazadoresmadridejos.propertyeditor.BudgetPropertyEditor;
import es.cazadoresmadridejos.util.validation.ValidationContainer;

@SessionAttributes({"budget"})
@Controller
public class BudgetCreateModifyController {

	@Autowired private BudgetManager budgetManager;
	@Autowired private BudgetValidator budgetValidator;
	@Autowired private ReasonManager reasonManager;
	
	@InitBinder
	public void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Throwable{
		binder.registerCustomEditor(Budget.class, new BudgetPropertyEditor(budgetManager));
	}
	
	private void init(ModelAndView mv, Budget budget){
		mv.addObject("reasons",reasonManager.findAllNotAssociated(budget.getId()));
	}
	
	@RequestMapping(value="/budgetCreateModify.html",method=RequestMethod.GET)
	public ModelAndView createModify(
			@RequestParam(value="id",required=false) Budget budgetLoad) throws Throwable {
		ModelAndView mv = new ModelAndView("budgetCreateModify");
		
		if(budgetLoad == null){
			budgetLoad = new Budget();
			mv.addObject("type","create");
		}else{
			mv.addObject("type","update");
		}
		mv.addObject("budget",budgetLoad);
		init(mv, budgetLoad);
		return mv;
	}
	@RequestMapping(value="/budgetCreateModifyFromAdd.html",method=RequestMethod.GET)
	public ModelAndView createModifyFromAdd(
			@ModelAttribute(value="budget") Budget budget) throws Throwable {
		ModelAndView mv = new ModelAndView("budgetCreateModify");
		
		if(budget.getId() == null){
			mv.addObject("type","create");
		}else{
			mv.addObject("type","update");
		}
		mv.addObject("budget",budget);
		init(mv,budget);
		return mv;
	}
	@RequestMapping(value="/budgetCreateModifyAdd.html")
	public ModelAndView createModifyAdd(
			@RequestParam(value="line")String line,
			@ModelAttribute(value="budget") Budget budget
			) throws Throwable {
		
		List<BudgetLine> lines = budget.getLines();
		BudgetLine budgetLine = new BudgetLine();
		if(line.equals("in")){
			budgetLine.setType(LineType.INCOMING);
		}else{
			budgetLine.setType(LineType.PAYMENT);
		}
		budgetLine.setBudget(budget);
		lines.add(budgetLine);
		
		Collections.sort(lines, new BLComparator());
		
		return null;
	}
	@RequestMapping(value="/budgetCreateModify.html",method=RequestMethod.POST)
	public ModelAndView submit(
			@ModelAttribute("budget") Budget budget, 
			BindingResult result, 
			SessionStatus status,
			HttpServletRequest request
			) throws Throwable {
		
		ModelAndView mv = new ModelAndView("redirect:index.html");
		List<ValidationContainer> errors = budgetValidator.validate(budget);
		if(errors.isEmpty()){
			mv.addObject("okMessage", "THE_BUDGET_PROCESS_IS_OK");
		}else{
			mv.addObject("errors",errors);
		}
		
//		List<BudgetLine> lines = budget.getLines();
//		for (BudgetLine budgetLine : lines) {
//			if(StringUtils.isBlank(budgetLine.getDescription()) &&budgetLine.getAmount() == null){
//				lines.remove(budgetLine);
//			}
//		}
		Iterator<BudgetLine> it = budget.getLines().iterator();
		while(it.hasNext()){
			BudgetLine budgetLine = it.next();
			if(StringUtils.isBlank(budgetLine.getDescription()) &&budgetLine.getAmount() == null){
				it.remove();
			}			
		}
		
		budgetManager.save(budget);
		mv.addObject("screen", "budgetList.html");
		return mv;
	}
	
	class BLComparator implements Comparator<BudgetLine>{

		@Override
		public int compare(BudgetLine o1, BudgetLine o2) {
			if(LineType.INCOMING.equals(o1.getType())){
				return -1;
			}
			if(LineType.INCOMING.equals(o2.getType())){
				return 1;
			}

			if(o1.getAmount() != null ){
				if(o2.getAmount() == null){
					return 1;
				}
				return o1.getAmount().compareTo(o2.getAmount());
			}
			
			if(o2.getAmount() != null){
				return -1;
			}
			
			return 0;
		}
		
	}
}
